package com.gitee.wsl.prism4j.languages

import com.gitee.wsl.prism4j.GrammarUtils
import com.gitee.wsl.prism4j.GrammarUtils.require
import com.gitee.wsl.prism4j.Prism4j
import com.gitee.wsl.prism4j.Prism4j.Companion.pattern
import com.gitee.wsl.prism4j.Prism4j.Companion.token
import com.gitee.wsl.prism4j.annotations.Extend
import com.gitee.wsl.prism4j.Prism4j.Pattern

@Suppress("unused")
@Extend("clike")
object Prism_groovy {
    fun create(prism4j: Prism4j): Prism4j.Grammar {
        val groovy: Prism4j.Grammar = GrammarUtils.extend(
            require(prism4j, "clike"),
            "groovy",
            token(
                "keyword",
                pattern(Pattern.compile("\\b(?:as|def|in|abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|trait|transient|try|void|volatile|while)\\b"))
            ),
            token(
                "string",
                pattern(
                    Pattern.compile("(\"\"\"|''')[\\s\\S]*?\\1|(?:\\$\\/)(?:\\$\\/\\$|[\\s\\S])*?\\/\\$"), false, true
                ),
                pattern(
                    Pattern.compile("([\"'\\/])(?:\\\\.|(?!\\1)[^\\\\\\r\\n])*\\1"), false, true
                )
            ),
            token(
                "number",
                pattern(
                    Pattern.compile(
                        "\\b(?:0b[01_]+|0x[\\da-f_]+(?:\\.[\\da-f_p\\-]+)?|[\\d_]+(?:\\.[\\d_]+)?(?:e[+-]?[\\d]+)?)[glidf]?\\b",
                        Pattern.CASE_INSENSITIVE
                    )
                )
            ),
            token(
                "operator",
                pattern(
                    Pattern.compile("(^|[^.])(?:~|==?~?|\\?[.:]?|\\*(?:[.=]|\\*=?)?|\\.[@&]|\\.\\.<|\\.{1,2}(?!\\.)|-[-=>]?|\\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\\|[|=]?|\\/=?|\\^=?|%=?)"),
                    true
                )
            ),
            token(
                "punctuation",
                pattern(Pattern.compile("\\.+|[{}\\[\\];(),:$]"))
            )
        )

        GrammarUtils.insertBeforeToken(
            groovy, "string",
            token(
                "shebang", pattern(
                    Pattern.compile("#!.+"),
                    false,
                    false,
                    "comment"
                )
            )
        )

        GrammarUtils.insertBeforeToken(
            groovy, "punctuation",
            token(
                "spock-block", pattern(
                    Pattern.compile("\\b(?:setup|given|when|then|and|cleanup|expect|where):")
                )
            )
        )

        GrammarUtils.insertBeforeToken(
            groovy, "function",
            token(
                "annotation", pattern(
                    Pattern.compile("(^|[^.])@\\w+"),
                    true,
                    false,
                    "punctuation"
                )
            )
        )

        // no string templates :(
        return groovy
    }
}
